//
// Created by none98 on 2021/9/10.
//

#ifndef LOGINSERVER_TCPCONNECTION_H
#define LOGINSERVER_TCPCONNECTION_H


#include <memory>
#include <mutex>
#include "InetAddress.h"
#include "Buffer.h"
#include "CallBacks.h"

class InetAddress;
class Channel;
class EventLoop;
class TcpConnection: public std::enable_shared_from_this<TcpConnection>{
    friend class Acceptor;
    friend class TcpServer;
public:
    using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
    TcpConnection(int fd,EventLoop* loop);
    virtual ~TcpConnection();


    void Send(const std::string &msg); //thread safe



    inline InetAddress GetRemoteAddress(){
        return remoteAddress;
    }

    inline InetAddress GetLocalAddress(){
        return localAddress;
    }

    inline void SetContext(std::shared_ptr<void> context){
        this->context=context;
    }

    inline void* GetContext(){
        return context.get();
    }

    inline int GetFd(){
        return fd;
    }

    long AddTimer(int hours,int minutes,int seconds,int milliSeconds, const TimerCallBack &callBack, int isCycle);

    void Close();

    void CancelTimer(long seq);


private:
    void HandleRead();
    void HandleWrite();
    void HandleError();

    //event set/get
    inline void SetOnMessage(const MessageCallBack &msgCallBack){
        this->msgCallBack=msgCallBack;
    }

    inline void SetOnClose(const TcpCallBack &tcpCallBack){
        this->closeCallBack = tcpCallBack;
    }
    inline void SetWriteComplete(const TcpCallBack &tcpCallBack){
        this->writeCompleteCallBack = tcpCallBack;
    }

    void SetEventLoop(EventLoop *loop);

    inline EventLoop* GetEventLoop(){
        return loop;
    }

    int fd;

    Buffer inputBuffer;
    //output buffer is thread safe, to guarantee mutiple Reactor io
    Buffer outputBuffer;
    std::mutex outMutex;

    //channel is an adapter, unique the Acceptor and TcpConnection
    std::unique_ptr<Channel> channel;

    //fd address information
    InetAddress localAddress;
    InetAddress remoteAddress;

    //TcpServer call Back;
    CloseInServerCallBack closeInTcpServer;
    //User set
    MessageCallBack msgCallBack;
    TcpCallBack closeCallBack;
    TcpCallBack writeCompleteCallBack;

    //for application context
    std::shared_ptr<void> context;
    EventLoop* loop;
};


#endif //LOGINSERVER_TCPCONNECTION_H
